package com.smartrobot.smartrobot.view;

import java.math.BigDecimal;


import android.app.Activity;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.ImageView;

import com.smartrobot.smartrobot.activity.ShowBigPicActivity;

//布局一改变即可收到通知
// 是一种ImgeView 可以用作放大缩小图片 左右移动图片


public class SmartPhotoView extends ImageView implements
		OnScaleGestureListener, OnTouchListener,
		ViewTreeObserver.OnGlobalLayoutListener,OnLongClickListener{

	// 设置最大 和 最小的范围
	private final float MAX_SIZE = 4.0f;
	private final float MIN_SIZE = 0.5f;
	private float COMMENT_SIZE = 1.0f;//第一张图片决定基础大小

	// 定义前一次按下的点
	private float lastX;
	private float lastY;

	private Matrix baseMatrix = new Matrix();
	// 用来获取当前图片的大小
	private final float[] matrixValues = new float[9];

	// 第一次使用标志 （用来是图片初始显示的时候居中）
	private boolean once = true;
	private boolean isScaling = false;// 图片正常显示的时候，是否拖动标志

	Interpolator sInterpolator = new AccelerateDecelerateInterpolator();

	// 监听手势
	ScaleGestureDetector sgDetector;
	
	//开始时间
	private long startTime=0;
	//解决结束当前activity问题
	private Activity activity = null;
	

	public SmartPhotoView(Context context) {
		super(context, null);// 调用第二个构造函数
		// TODO Auto-generated constructor stub
	}

	public SmartPhotoView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// 设置 scaletype 否则无法使用matrix
		super.setScaleType(ScaleType.MATRIX);
		
		// 设置监听
		sgDetector = new ScaleGestureDetector(context, this);
		this.setOnTouchListener(this);

	}

	private void BitmapScaleFitScreen() {
		RectF rect = getRectF();
		float deltaX = 0;
		float deltaY = 0;

		int width = getWidth();
		int height = getHeight();

		// 图片 宽 比 屏幕 大
		if (rect.width() >= width) {
			if (rect.left > 0) {
				// 移到负区域 --》 居中
				deltaX = -rect.left;
			}
			if (rect.right < width) {
				deltaX = width - rect.right;
			}
		}
		if (rect.height() >= height) {
			if (rect.top > 0) {
				deltaY = -rect.top;
			}
			if (rect.bottom < height) {
				deltaY = height - rect.bottom;
			}
		}
		// 若是图片 比 屏幕小 那么 (屏幕宽 - 图片宽)*0.5 - （图片right - 宽）--》相对移动位置
		if (rect.width() < width) {
			deltaX = width * 0.5f - rect.right + 0.5f * rect.width();
		}
		if (rect.height() < height) {
			deltaY = height * 0.5f - rect.bottom + 0.5f * rect.height();
		}
		baseMatrix.postTranslate(deltaX, deltaY);
	}

	// 获得图片改变后的信息
	RectF getRectF() {

		Matrix matrix = baseMatrix;
		RectF rect = new RectF();
		Drawable d = getDrawable();
		if (null != d) {
			rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
			baseMatrix.mapRect(rect);
		}
		return rect;
	}

	// 计算 当前图片规模 是否超过最大最小值
	float getScale() {
		baseMatrix.getValues(matrixValues);
		return matrixValues[Matrix.MSCALE_X];
	}
	

	// 监听放大缩小的手势
	public boolean onScale(ScaleGestureDetector detector) {

		isScaling = false;// 不可拖拽 非原型图片

		float scale = getScale(); // 获得当前图片缩放
		float scaleFactor = detector.getScaleFactor();// 图片应当缩放

		if (getDrawable() == null) // 没有图片直接显示
			return true;

		// 缩放图片 必须 有最大和最小
		if ((scale < MAX_SIZE && scaleFactor > 1.0f)
				|| (scale > MIN_SIZE && scaleFactor < 1.0f)) {
			baseMatrix.postScale(scaleFactor, scaleFactor,
					detector.getFocusX(), detector.getFocusY());
			BitmapScaleFitScreen();
			setImageMatrix(baseMatrix);
			System.out.println("scale  " + scale);

			System.out.println("显示出结果");
		}

		return true;
	}

	@Override
	public boolean onScaleBegin(ScaleGestureDetector detector) {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public void onScaleEnd(ScaleGestureDetector detector) {
		// TODO Auto-generated method stub

	}

	@Override
	protected void onAttachedToWindow() {
		super.onAttachedToWindow();
		// 调用 onGlobalLayout 对图片进行调整 居中
		getViewTreeObserver().addOnGlobalLayoutListener(this);

	}

	@Override
	protected void onDetachedFromWindow() {
		super.onDetachedFromWindow();
		getViewTreeObserver().removeGlobalOnLayoutListener(this);

	}
	
	// 改变布局 第一次 让 图片 适合显示
	public void onGlobalLayout() {

		// 获得图片
		Drawable d = getDrawable();
		 //由于使用imageload有默认显示图片，会初始化图片的位置，导致有bug出现
		if(d != null)
		if (once) {
			
			// 获得view width hegith
			int width = getWidth();
			int height = getHeight();
			// 获得图片长 宽
			int dwidth = d.getIntrinsicWidth();
			int dheight = d.getIntrinsicHeight();




			float scale = 1.0f;// 设置初始大小
			if(dwidth < width){
				//图片宽比屏幕小
				scale = width * 1.0f / dwidth;
			}
			if(dwidth > width){
				//图片宽比屏幕大
				scale = width * 1.0f / dwidth;
			}

            Log.d("-------------------->dwidth ",""+dwidth);
            Log.d("-------------------->dheight ",""+dheight);
            Log.d("-------------------->width ",""+width);
            Log.d("-------------------->height ",""+height);
            Log.d("-------------------->scale ",""+scale);
            Log.d("-------------------->full   ",""+ (scale * dwidth));


			// 设置初始最小为 图片 初始大小
			COMMENT_SIZE = scale;
			
			// 将图片 -->移到中心 ---> 图片中心缩放
			baseMatrix.postTranslate((width - dwidth) / 2,
					(height - dheight) / 2);
			baseMatrix.postScale(scale, scale, getWidth() / 2, getHeight() / 2);
			setImageMatrix(baseMatrix);
			once = false;
		}

	}
	

	// 监听触碰
	public boolean onTouch(View v, MotionEvent event) {

		switch (event.getAction() & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			
			
			startTime = System.currentTimeMillis();

			lastX = event.getX();
			lastY = event.getY();

			break;
		case MotionEvent.ACTION_MOVE:

			// 图片大于屏幕 可以 拖拽图片
			if (getScale() > COMMENT_SIZE)
				DragPic(event);

			BigDecimal bg1 = new BigDecimal(getScale());
			BigDecimal bg2 = new BigDecimal(COMMENT_SIZE);

			// 图片 等于 初始大小 可以来回拖拽 但是要返回 由于我们使用时间进行测量，因此返回时
			// 有细微改变大小 所以要看小数点后4位判断是否变回原图
			if (bg1.setScale(4, BigDecimal.ROUND_HALF_UP).floatValue() == bg2
					.setScale(4, BigDecimal.ROUND_HALF_UP).floatValue())
				DragCommentPic(event);

			break;
		case MotionEvent.ACTION_UP:

			// 判断 当前图片大小 是否 小于正常
			if (getScale() < COMMENT_SIZE) {
				RectF rect = getRectF();
				// 通过动画 返回
				this.post(new ZoomReturnRunnable(getScale(), COMMENT_SIZE, rect
						.centerX(), rect.centerY()));
			}

//			System.out.println("COMMENT_SIZE " + COMMENT_SIZE);
//			System.out.println("getScale() " + isScaling);
//			System.out.println("isScaling " + isScaling);

			// 图片拉动了，需要启动动画修复
			if (getScale() == COMMENT_SIZE && isScaling) {
				startCommentAmonation(event);
			}
			
			//若是仅仅点击 ，就立即关闭
			long endTime = System.currentTimeMillis();
			if((endTime - startTime) < 150)
				if(activity != null)
					activity.finish();

			break;

		}

		return sgDetector.onTouchEvent(event);// 传递触发事件
	}
	
	public void setCloseActivity(ShowBigPicActivity _activity){
		
		activity = _activity;
		
	}

	void DragPic(MotionEvent event) {
		RectF rect = getRectF();
		float dx = 0.0f;
		float dy = 0.0f;

		// 那么可以横向拉动 图片宽 比 屏幕大
		if (rect.width() > getWidth() && rect.height() <= getHeight()) {
			dx = event.getX() - lastX;
			lastX = event.getX();

			// 处理dx
			if (dx > 0) { // 图片向左看 rect.centerX() + dx <= (rect.width()/2)
				if (rect.centerX() + dx > (rect.width() / 2))
					// 若是超过边界，直接移到边界
					dx = rect.width() / 2 - rect.centerX();

			} else {// 图片向右看

				// 边界 最右边 right 必须超过
				if (rect.right + dx <= getRight()) {
					dx = getRight() - rect.right;
				}

			}
			baseMatrix.postTranslate(dx, 0);
		}

		// 可以竖方向拉动图片
		if (rect.width() <= getWidth() && rect.height() > getHeight()) {

			dy = event.getY() - lastY;
			lastY = event.getY();

			// 处理dy
			if (dy > 0) {
				// 图片向上 手指一动距离大于顶部 那么就计算实际移动 否则 按手指移动距离
				if (rect.top + dy > ((this.getHeight() - rect.height()) / 2f))
					dy = -rect.top;
			} else {
				// 图片向下 手指一动距离大于底部 那么就计算实际移动 否则 按手指移动距离
				if (rect.bottom + dy <= this.getHeight())
					dy = this.getHeight() - rect.bottom;
			}

			baseMatrix.postTranslate(0, dy);
		}
		if (rect.width() > getWidth() && rect.height() > getHeight()) {
			dx = event.getX() - lastX;
			dy = event.getY() - lastY;
			lastX = event.getX();
			lastY = event.getY();

			// 处理dx
			if (dx > 0) { // 图片向左看 rect.centerX() + dx <= (rect.width()/2)
				if (rect.centerX() + dx > (rect.width() / 2))
					// 若是超过边界，直接移到边界
					dx = rect.width() / 2 - rect.centerX();

			} else {// 图片向右看

				// 边界 最右边 right 必须超过
				if (rect.right + dx <= getRight())
					dx = getRight() - rect.right;

			}

			// 处理dy
			if (dy > 0) {
				// 图片向上 手指一动距离大于顶部 那么就计算实际移动 否则 按手指移动距离
				if (rect.top + dy > ((this.getHeight() - rect.height()) / 2f))
					dy = -rect.top;

			} else {
				// 图片向下 手指一动距离大于底部 那么就计算实际移动 否则 按手指移动距离
				if (rect.bottom + dy <= this.getHeight())
					dy = this.getHeight() - rect.bottom;

			}

			baseMatrix.postTranslate(dx, dy);
		}

		setImageMatrix(baseMatrix);

	}

	// 根据不同选择不同动画
	void startCommentAmonation(MotionEvent event) {

		RectF rect = getRectF();
		float startX = 0.0f;
		float endX = this.getWidth() * 1f;
		// 在这里我们要考虑 如果图片宽 比 屏幕小的时候 就是居中那么开始和结束就不一样
		if (rect.width() < this.getWidth()) {

			startX = (this.getWidth() - rect.width()) * 0.5f;
			endX = (this.getWidth() + rect.width()) * 0.5f;

		}

		if (rect.left > startX) {
			this.post(new ZoomCommentRunnable(rect.left, startX));
		}

		if (rect.right < endX) {
			this.post(new ZoomCommentRunnable(rect.right, endX));
		}

	}

	void SmallPicChangeFrame() {
		// 图片 比 imgveiw小需要改变边框才能够正常显示
		RectF rect = getRectF();
//		System.out.println("改变边框");
//		System.out.println("left -->" + rect.left);
//		System.out.println("right -->" + rect.right);
//		System.out.println("top -->" + rect.top);
//		System.out.println("bottom -->" + rect.bottom);

		SmartPhotoView.this.setFrame(10, 10, (int) rect.right,
				(int) rect.bottom);
	}

	// 左右移动 正常的图片 但是要返回
	void DragCommentPic(MotionEvent event) {

		RectF rect = getRectF();
		float dx = 0.0f;
		float dy = 0.0f;

		dx = event.getX() - lastX;
		lastX = event.getX();// 避免放大过大

		if (dx > 0) {
			baseMatrix.postTranslate(dx, 0);

		} else {
			baseMatrix.postTranslate(dx, 0);
		}

		isScaling = true;
		setImageMatrix(baseMatrix);

	}

	// 创建动画 让图片返回原来位置
	class ZoomCommentRunnable implements Runnable {

		float currentPos;
		float targertPos;
		float move;

		public ZoomCommentRunnable(float currentPos, float targertPos) {
			this.currentPos = currentPos;
			this.targertPos = targertPos;
			// 设置20加载次数 (相当于动画帧)
			move = (targertPos - currentPos) / 20;
		}

		@Override
		public void run() {

			int i = 20;
			while (i > 0) {
				baseMatrix.postTranslate(move, 0);
				setImageMatrix(baseMatrix);
				--i;
			}

			isScaling = false;// 弹回结束后，不在触发事件

		}

	}

	// 图片缩小后 使用线程动画返回到设定好的
	class ZoomReturnRunnable implements Runnable {

		float currentScale, targertScale;
		long startTime;// 设置时间作为动画基数
		float focausX, focausY;// 缩放中心

		public ZoomReturnRunnable(float currentScale, float targertScale,
				float focausX, float focausY) {

			this.currentScale = currentScale;
			this.targertScale = targertScale;
			this.focausX = focausX;
			this.focausY = focausY;
			startTime = System.currentTimeMillis();

		}

		@Override
		public void run() {

			if (null == getDrawable())
				return;

			while (true) {
				float t = interpolate();
				float scale = currentScale + t * (targertScale - currentScale);
				float deltaScale = scale / getScale();// 获得长和宽的缩放

				baseMatrix.postScale(deltaScale, deltaScale, focausX, focausY);

				setImageMatrix(baseMatrix);

				if (getScale() >= COMMENT_SIZE)
					break;

			}

			isScaling = true;

		}

		float interpolate() {
			float t = 1f * (System.currentTimeMillis() - startTime) / 200;
			t = Math.min(1f, t);
			t = sInterpolator.getInterpolation(t);
			return t;
		}

	}

	@Override
	public boolean onLongClick(View v) {
		
		System.out.println("长按。。。");
		
		return false;
	}



}
